package com.bootdo.api;

import com.bootdo.backlist.converter.ConvertDomainUtils;
import com.bootdo.backlist.dto.AppuserDTO;
import com.bootdo.backlist.form.AppuserForm;
import com.bootdo.backlist.form.NoteCodeForm;
import com.bootdo.backlist.service.AppuserService;
import com.bootdo.backlist.service.YunPianService;
import com.bootdo.backlist.vo.AppuserVO;
import com.bootdo.common.enums.ResultEnum;
import com.bootdo.common.interfaces.Add;
import com.bootdo.common.interfaces.Login;
import com.bootdo.common.interfaces.Reset;
import com.bootdo.common.interfaces.Transfer;
import com.bootdo.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Zengcx
 * @date 2019-04-10 17:27
 */
@RestController
@RequestMapping("/api/user")
@Slf4j
public class ApiAppUserController {
    @Autowired
    private AppuserService appuserService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private YunPianService yunPianService;

    /**
     * 用户注册
     * @param appuserForm
     * @param bindingResult
     * @return
     */
    @PostMapping("/register")
    public R register(@Validated(value = {Add.class}) AppuserForm appuserForm, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            log.error("【参数错误】appuserForm={}",appuserForm);
            return R.error(bindingResult.getFieldError().getDefaultMessage());
        }
        if(AccountValidatorUtil.isRegEX(appuserForm.getNickname())){
            return R.error("昵称不能包含特殊字符");
        }
        if(AccountValidatorUtil.isRegEX(appuserForm.getAccount())){
            return R.error("账号不能包含特殊字符");
        }

        if (!AccountValidatorUtil.isMobile(appuserForm.getPhone())){
            return R.error("请输入正确的手机号");
        }

        if (!AccountValidatorUtil.isPassword(appuserForm.getPassword())){
            return R.error("请输入6-20位密码");
        }

        if (!AccountValidatorUtil.isUsername(appuserForm.getAccount())){
            return R.error("请输入5-20位账号，仅支持大小写字母");
        }

        Map<String,Object> map = new HashMap<>();
        map.put("account",appuserForm.getAccount());
        List<AppuserDTO> list = appuserService.list(map);
        if (!CollectionUtils.isEmpty(list)){
            return R.error(ResultEnum.USER_USE.getMessage());
        }
        map.remove("account");
        map.put("phone",appuserForm.getPhone());
        List<AppuserDTO> dtoList = appuserService.list(map);
        if (!CollectionUtils.isEmpty(dtoList)){
            return R.error(ResultEnum.PHONE_USE_REGISTER.getMessage());
        }
        if (!appuserForm.getPassword().equalsIgnoreCase(appuserForm.getRestPassword())){
            return R.error(ResultEnum.NOT_AGREE.getMessage());
        }
        R r = yunPianService.valid(new NoteCodeForm(appuserForm.getPhone() + "_code", appuserForm.getCode()));
        if ((Integer)r.get("code") != 0){
            return r;
        }
        appuserForm.setPassword(MD5Utils.encrypt(appuserForm.getPassword()));
        R save = appuserService.save(ConvertDomainUtils.convertObject(appuserForm, AppuserDTO.class));
        if ((Integer)save.get("code") == 0){
            redisTemplate.expire(appuserForm.getPhone() + "_code",1,TimeUnit.SECONDS);
        }
        return save;

    }

    /**
     * 用户登录
     * @param appuserForm
     * @param bindingResult
     * @return
     */
    @PostMapping("/login")
    public R login(@Validated(value = {Login.class}) AppuserForm appuserForm, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            log.error("【参数错误】appuserForm={}",appuserForm);
            return R.error(bindingResult.getFieldError().getDefaultMessage());
        }
        ValueOperations operations = redisTemplate.opsForValue();
        appuserForm.setPassword(MD5Utils.encrypt(appuserForm.getPassword()));
        AppuserDTO appuserDTO = appuserService.login(ConvertDomainUtils.convertObject(appuserForm, AppuserDTO.class));
        if (appuserDTO != null) {
            AppuserVO appuserVO = ConvertDomainUtils.convertObject(appuserDTO, AppuserVO.class);
            appuserVO.setToken(KeyUtil.getToken());
            if (appuserDTO != null){
                operations.set(appuserVO.getToken(),appuserVO.getToken());
                redisTemplate.expire(appuserVO.getToken(),7, TimeUnit.DAYS);
                return R.ok(ResultEnum.LOGIN_SUCCESS.getMessage()).put("data", appuserVO);
            }
        }

        return R.error(ResultEnum.LOGIN_FAIL.getMessage());
    }

    /**
     * 验证token
     * @param token
     * @return
     */
    @GetMapping("/validToken")
    public R validToken(@RequestParam("token") String token){
        ValueOperations operations = redisTemplate.opsForValue();
        String result = (String) operations.get(token);
        //redis中没有该数据说明已经过期或不存在
        if (result == null) {
            return R.error(ResultEnum.TOKEN_EXPIRE.getMessage());
        }
        //传的token和Redis中不匹配，验证失败
        if (!result.equalsIgnoreCase(token)){
            return R.error(ResultEnum.TOKEN_VAILD_FAIL.getMessage());
        }
        return R.ok().put("token",result);
    }

    /**
     * 获取用户详情
     * @param userId 用户ID
     * @return
     */
    @GetMapping("/getUser")
    public R getUserInfo(@RequestParam("userId") Long userId){
        if (userId == null){
            return R.error(ResultEnum.PARAM_ERROR.getMessage());
        }
        AppuserDTO appuserDTO = appuserService.get(userId);
        if (appuserDTO != null) {
            AppuserVO appuserVO = ConvertDomainUtils.convertObject(appuserDTO, AppuserVO.class);
            return R.ok().put("data",appuserVO);
        }
        return R.error(ResultEnum.DATA_NOT_EXIST.getMessage());
    }

    /**
     * 转移积分
     * @param appuserForm
     * @param bindingResult
     * @return
     */
    @PostMapping("/transfer")
    public R transfer(@Validated(Transfer.class) AppuserForm appuserForm,BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            log.error("【参数错误】appuserForm={}",appuserForm);
            return R.error(bindingResult.getFieldError().getDefaultMessage());
        }
        //接收人
        AppuserDTO appuserDTO = appuserService.get(appuserForm.getUserId());
        //转移人
        AppuserDTO transferDto = appuserService.get((appuserForm.getTransferUserId()));
        if (transferDto.getIntegral().compareTo(appuserForm.getIntegral()) < 0){
            return R.error(ResultEnum.INTEGRAL_INSUFFICIENT.getMessage());
        }

        appuserDTO.setIntegral(appuserDTO.getIntegral().add(appuserForm.getIntegral()));
        transferDto.setIntegral(transferDto.getIntegral().subtract(appuserForm.getIntegral()));

        R r = appuserService.update(appuserDTO);
        R r1 = appuserService.update(transferDto);
        if ((Integer) r.get("code") != 0 || (Integer) r1.get("code") != 0){
            return R.error(ResultEnum.TRANSFER_FAIL.getMessage());
        }else {
            return R.ok();
        }
    }

    /**
     * 重置密码
     * @param appuserForm
     * @param bindingResult
     * @return
     */
    @PostMapping("/reset/pwd")
    public R resetPwd(@Validated(Reset.class) AppuserForm appuserForm, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            log.error("【参数错误】appuserForm={}",appuserForm);
            return R.error(bindingResult.getFieldError().getDefaultMessage());
        }
        if (!appuserForm.getPassword().equalsIgnoreCase(appuserForm.getRestPassword())){
            return R.error(ResultEnum.NOT_AGREE.getMessage());
        }
        R r = yunPianService.valid(new NoteCodeForm(appuserForm.getPhone(), appuserForm.getCode()));
        if ((Integer)r.get("code") != 0){
            return r;
        }
        Map<String,Object> map = new HashMap<>();
        map.put("phone",appuserForm.getPhone());
        List<AppuserDTO> list = appuserService.list(map);
        AppuserDTO appuserDTO = list.get(0);
        appuserDTO.setPassword(MD5Utils.encrypt(appuserForm.getPassword()));
        return appuserService.update(appuserDTO);
    }

}
